package main

import (
	"context"
	"fmt"
	"n-server/config"
	"n-server/internal/container"
	"n-server/pkg/cache"
	"n-server/pkg/database"
	"n-server/pkg/logger"
	"n-server/pkg/redis"
	"n-server/pkg/utils/jwt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"go.uber.org/zap"
)

// @title N-Server API
// @version 1.0
// @description Swagger API 默认不整合此依赖，需要手动引入
// @host localhost:8080
// @BasePath /api
func main() {
	// 1. 初始化配置
	c, err := config.Init()
	if err != nil {
		fmt.Printf("Init configs failed, err:%v\n", err)
		return
	}

	// 2. 初始化日志
	logger.Init(c.Log.Level, c.Log.Encoding, c.Log.OutputPath, c.Log.ErrorPath, c.Log.InitialFields)
	defer logger.L().Sync() // 确保所有缓冲条目都被写入

	logger.L().Info("Application configuration init successfully", zap.Any("config", c))

	// 3. 初始 JWT
	jwt.Init(c.JWT)

	// 4. 初始化数据库
	db, err := database.Init(c.Database)
	if err != nil {
		logger.L().Fatal("Init database failed", zap.Error(err))
	}
	defer database.Close(db)

	// 5. 初始化 Redis
	rdb := redis.Init(c.Redis)
	defer rdb.Close()

	// 6. 初始化 LRUCache
	cache := cache.Init(1000)

	// 7. 依赖注入
	container := container.Init(c, db, rdb, cache)

	// 8. 设置 Gin 路由
	r := container.SetupRouter()

	// 9. 启动 HTTP 服务器
	addr := fmt.Sprintf(":%d", c.Server.Port)
	server := &http.Server{
		Addr:         addr,
		Handler:      r,
		ReadTimeout:  c.Server.ReadTimeout,
		WriteTimeout: c.Server.WriteTimeout,
	}

	go func() {
		logger.L().Info(fmt.Sprintf("Server is running on %s", addr))
		if err = server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.L().Fatal("Server startup failed", zap.Error(err))
		}
	}()

	// 10. 优雅关机
	quit := make(chan os.Signal, 1)
	// 监听 syscall.SIGINT (Ctrl+C) 和 syscall.SIGTERM (kill 命令)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit // 阻塞直到接受到信号

	logger.L().Info("Shutting down server...")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // 5 秒优雅关机超时
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		logger.L().Fatal("Server forced to shutdown", zap.Error(err))
	}

	logger.L().Info("Server exited gracefully")

}
